package com.cvte.boe.media;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;

import com.cvte.boe.media.adapter.FileBrowserAdapter;
import com.cvte.boe.media.controller.LRUThumbManager;
import com.cvte.boe.media.controller.MediaFileManager;
import com.cvte.boe.media.model.LocalDeviceInfo;
import com.cvte.boe.media.model.LocalMediaInfo;
import com.cvte.boe.media.utils.BitmapUtils;
import com.cvte.boe.media.utils.ComparatorUtil;
import com.cvte.boe.media.utils.LogUtil;
import com.cvte.boe.media.utils.PlayerUtil;
import com.cvte.boe.media.utils.StringUtils;
import com.cvte.boe.media.utils.constant.Constant;
import com.cvte.boe.media.views.widget.MarqueeTextView;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by wuguitong on 2018/4/10.
 */
public class MediaFileBrowserActivity extends Activity implements AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
    private final String TAG = MediaFileBrowserActivity.this.getClass().getSimpleName();
    private static final int MSG_START_LOAD_THUMB_TASK = 0;
    private static final int MSG_STOP_LOAD_THUMB_TASK = 1;
    private Context mContext;
    private int mThumbWidth;
    private int mThumbHeight;
    private int mRoundAngle;
    private int halfRoundAngle;
    private int cutXPosition;
    private int cutYposition;
    private int cutWidth;
    private int cutHeight;
    private LocalDeviceInfo mCurrDeviceInfo;
    private MarqueeTextView tvFilePath;
    private GridView mediaFileBrowser;
    private String mCurrentDir;
    private String mRootDir;
    private FileBrowserAdapter fileBrowserAdapter;
    private ComparatorUtil.MediaFileComparator mediaFileComparator;
    private List<LocalMediaInfo> mLocalMediaInfoList;
    private MediaFileLoaderTask mMediaFileLoaderTask;
    private Map<String, Integer> dirFocusPosMap;
    private MediaThumbnailLoaderTask mMediaThumbnailLoaderTask;
    private int lastFirstVisiblePos;
    private int lastLastVisiblePos;
    private int curFirstVisiblePos;
    private int curLastVisiblePos;
    private Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message message) {
            switch (message.what) {
                case MSG_START_LOAD_THUMB_TASK:
                    if(mMediaThumbnailLoaderTask != null){
                        mMediaThumbnailLoaderTask.cancel(true);
                    }
                    curFirstVisiblePos = mediaFileBrowser.getFirstVisiblePosition();
                    curLastVisiblePos = mediaFileBrowser.getLastVisiblePosition();
                    if(curFirstVisiblePos < mLocalMediaInfoList.size() && curLastVisiblePos < mLocalMediaInfoList.size() && (curFirstVisiblePos <= curLastVisiblePos)) {
                        mMediaThumbnailLoaderTask = new MediaThumbnailLoaderTask();
                        List<LocalMediaInfo> list = new ArrayList<LocalMediaInfo>();
                        list.addAll(mLocalMediaInfoList.subList(curFirstVisiblePos,curLastVisiblePos + 1));
                        mMediaThumbnailLoaderTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,list);
                    }
                    break;
                case MSG_STOP_LOAD_THUMB_TASK:
                    if(mMediaThumbnailLoaderTask != null){
                        mMediaThumbnailLoaderTask.cancel(true);
                    }
                    break;
                default:
                    break;
            }
            return true;
        }
    });

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = this;
        lastFirstVisiblePos = 0;
        lastLastVisiblePos = 0;
        curFirstVisiblePos = 0;
        curLastVisiblePos = 0;
        mThumbWidth = mContext.getResources().getDimensionPixelSize(R.dimen.thumb_width);
        mThumbHeight = mContext.getResources().getDimensionPixelSize(R.dimen.thumb_height);
        mRoundAngle = mContext.getResources().getDimensionPixelSize(R.dimen.thumb_round_angle);
        halfRoundAngle = (int) mContext.getResources().getDimension(R.dimen.thumb_half_round_angle);
        cutXPosition = (int) mContext.getResources().getDimension(R.dimen.thumb_cut_xpoition);
        cutYposition = (int) mContext.getResources().getDimension(R.dimen.thumb_cut_yposition);
        cutWidth = (int) mContext.getResources().getDimension(R.dimen.thumb_cut_width);
        cutHeight = (int) mContext.getResources().getDimension(R.dimen.thumb_cut_height);
        setContentView(R.layout.activity_media_file_browser);
        Intent intent = getIntent();
        Bundle bundle = intent.getBundleExtra(LocalDeviceInfo.DEVICE_COMPRESS_NAME);
        mCurrDeviceInfo = new LocalDeviceInfo();
        mCurrDeviceInfo.decompress(bundle);
        mRootDir = StringUtils.formatMountPointWithoutSeparator(mCurrDeviceInfo.getMountPath());
        mCurrentDir = mRootDir;
        mediaFileComparator = new ComparatorUtil.MediaFileComparator();
        dirFocusPosMap = new HashMap<String, Integer>();
        dirFocusPosMap.clear();
        tvFilePath = (MarqueeTextView) findViewById(R.id.tv_file_path);
        tvFilePath.setMarqueeState(true);
        tvFilePath.setText(StringUtils.transformFileMountPathToDevNamePath(mCurrDeviceInfo.getMountPath(),
                mCurrDeviceInfo.getMountPath(), mCurrDeviceInfo.getDevName()));
        mediaFileBrowser = (GridView) findViewById(R.id.media_file_browser);
        mLocalMediaInfoList = new ArrayList<LocalMediaInfo>();
        fileBrowserAdapter = new FileBrowserAdapter(mContext, mLocalMediaInfoList);
        MediaApplication.registerMountActionListener(mountActionListener);
        mediaFileBrowser.setOnItemSelectedListener(this);
        mediaFileBrowser.setOnItemClickListener(this);
        mediaFileBrowser.setAdapter(fileBrowserAdapter);
        mMediaFileLoaderTask = new MediaFileLoaderTask();
        mMediaFileLoaderTask.execute(mCurrentDir);
    }

    @Override
    protected void onDestroy() {
        MediaApplication.unRegisterMountActionListener(mountActionListener);
        super.onDestroy();
    }

    MediaApplication.MountActionListener mountActionListener = new MediaApplication.MountActionListener() {
        @Override
        public void onReceive(String volumePath, boolean mount) {
            if (StringUtils.formatMountPointWithSeparator(volumePath).equals(StringUtils.formatMountPointWithSeparator(mCurrDeviceInfo.getMountPath()))) {
                if (mount) {

                } else {
                    Toast.makeText(mContext,mContext.getResources().getString(R.string.usb_removed_info),Toast.LENGTH_SHORT).show();
                    MediaFileBrowserActivity.this.finish();
                }
            }
        }
    };

    @Override
    public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
        fileBrowserAdapter.setSelectPosition(i);
        curFirstVisiblePos = mediaFileBrowser.getFirstVisiblePosition();
        curLastVisiblePos = mediaFileBrowser.getLastVisiblePosition();
        if((mMediaFileLoaderTask != null) && (mMediaFileLoaderTask.getStatus() == AsyncTask.Status.FINISHED)){
            if(lastLastVisiblePos != curLastVisiblePos || lastFirstVisiblePos != curFirstVisiblePos){
                lastLastVisiblePos = curLastVisiblePos;
                lastFirstVisiblePos = curFirstVisiblePos;
                mHandler.sendEmptyMessage(MSG_STOP_LOAD_THUMB_TASK);
                mHandler.removeMessages(MSG_START_LOAD_THUMB_TASK);
                mHandler.sendEmptyMessageDelayed(MSG_START_LOAD_THUMB_TASK,1000);
            }
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> adapterView) {
    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
        if (mLocalMediaInfoList.size() > position) {
            Intent intent = new Intent();
            //intent.putExtra(PlayerUtil.CURRENT_FILE_DATA,mLocalMediaInfoList.get(position).compress());
            //intent.putExtra(PlayerUtil.CURRENT_FILE_PATH,mLocalMediaInfoList.get(position).getParentPath());
            intent.setAction(Intent.ACTION_VIEW);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            File file = new File(mLocalMediaInfoList.get(position).getFileAllName());
            switch (mLocalMediaInfoList.get(position).getFileType()) {
                case Constant.MediaType.VIDEO:
                    intent.setClass(mContext,VideoPlayActivity.class);
                    intent.setDataAndType(Uri.fromFile(file), "video/*");
                    mContext.startActivity(intent);
                    break;
                case Constant.MediaType.AUDIO:
                    intent.setClass(mContext,AudioPlayActivity.class);
                    intent.setDataAndType(Uri.fromFile(file), "audio/*");
                    mContext.startActivity(intent);
                    break;
                case Constant.MediaType.IMAGE:
                    intent.setClass(mContext,ImagePlayActivity.class);
                    intent.setDataAndType(Uri.fromFile(file), "image/*");
                    mContext.startActivity(intent);
                    break;
                case Constant.MediaType.FOLDER:
                    dirFocusPosMap.put(mCurrentDir, position);
                    mCurrentDir = StringUtils.formatMountPointWithoutSeparator(mLocalMediaInfoList.get(position).getFileAllName());
                    dirFocusPosMap.put(mCurrentDir, 0);
                    mMediaFileLoaderTask = new MediaFileLoaderTask();
                    mMediaFileLoaderTask.execute(mCurrentDir);
                    break;
                default:
                    Toast.makeText(mContext, mContext.getResources().getString(R.string.file_not_support_info), Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (mCurrentDir.equals(mRootDir)) {
                if (mMediaFileLoaderTask != null) {
                    mMediaFileLoaderTask.cancel(true);
                }
                mHandler.sendEmptyMessage(MSG_STOP_LOAD_THUMB_TASK);
                if (dirFocusPosMap != null) {
                    dirFocusPosMap.clear();
                }
                mHandler.removeMessages(MSG_START_LOAD_THUMB_TASK);
                mHandler.removeMessages(MSG_STOP_LOAD_THUMB_TASK);
                //LRUThumbManager.getInstance().cleanThumb();
                MediaFileManager.getInstance().cleanToDirMediaFilesMap();
                this.finish();
            } else {
                mCurrentDir = mCurrentDir.substring(0, mCurrentDir.lastIndexOf(File.separator));
                mMediaFileLoaderTask = new MediaFileLoaderTask();
                mMediaFileLoaderTask.execute(mCurrentDir);
            }
            return true;
        }
        return false;
    }
    private class MediaThumbnailLoaderTask extends AsyncTask<List<LocalMediaInfo>, Void, Void> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            if (isCancelled()) {
                LogUtil.d(TAG,"onProgressUpdate isCancelled" );
                return;
            }
            fileBrowserAdapter.notifyDataSetChanged();
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
        }

        @Override
        protected Void doInBackground(List<LocalMediaInfo>... lists) {
            List<LocalMediaInfo> list = new ArrayList<LocalMediaInfo>();
            list.addAll(lists[0]);
            for (LocalMediaInfo info : list) {
                if (isCancelled()) {
                    return null;
                }
                Bitmap tempBitmap = null;
                MediaMetadataRetriever rert = null;
                switch (info.getFileType()) {
                    case Constant.MediaType.IMAGE:
                        try {
                            String key = info.getFileAllName();
                            Bitmap bitmap = LRUThumbManager.getInstance().getImageThumb(key);
                            if (bitmap == null) {
                                tempBitmap = BitmapUtils.comp(key, mThumbWidth, mThumbHeight);
                                if (tempBitmap != null) {
                                    if (tempBitmap.getHeight() == 0 || tempBitmap.getWidth() == 0) {
                                        continue;
                                    }
                                    tempBitmap = BitmapUtils.comp(tempBitmap, mThumbWidth, mThumbHeight);
                                    bitmap = BitmapUtils.getRoundedCornerAndCutBitmap(tempBitmap, halfRoundAngle, cutXPosition, cutYposition, cutWidth, cutHeight);
                                    LRUThumbManager.getInstance().putImageThumb(key, bitmap);
                                    publishProgress();
                                }
                            }
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        } catch (OutOfMemoryError error) {
                            LogUtil.d("OutOfMemoryError", "OutOfMemoryError ##### will not show compress picture");
                        } finally {
                            if (tempBitmap != null && !tempBitmap.isRecycled()) {
                                tempBitmap.recycle();
                            }
                        }
                        break;
                    case Constant.MediaType.VIDEO:
                        try {
                            String key = info.getFileAllName();
                            Bitmap bitmap = LRUThumbManager.getInstance().getImageThumb(key);
                            if (bitmap == null) {

                                rert = new MediaMetadataRetriever();
                                if (rert != null) {
                                    rert.setDataSource(info.getFileAllName());
                                    String strWidth = rert.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
                                    String strHeight = rert.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
                                    if ((!StringUtils.isEmpty(strWidth)) && (!StringUtils.isEmpty(strHeight))) {
                                        int width = Integer.valueOf(strWidth);
                                        int height = Integer.valueOf(strHeight);
                                        if (width > 0 && height > 0 && width * height < 1920 * 1200) {
                                            tempBitmap = rert.getFrameAtTime();
                                            if (tempBitmap != null) {
                                                tempBitmap = BitmapUtils.comp(tempBitmap, mThumbWidth, mThumbHeight);
                                                if (tempBitmap != null) {
                                                    bitmap = BitmapUtils.getRoundedCornerAndCutBitmap(tempBitmap, halfRoundAngle, cutXPosition, cutYposition, cutWidth, cutHeight);
                                                    LRUThumbManager.getInstance().putImageThumb(key, bitmap);
                                                    publishProgress();
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        } catch (OutOfMemoryError error) {
                            LogUtil.d("OutOfMemoryError", "OutOfMemoryError ##### will not show compress picture");
                        } finally {
                            if (rert != null) {
                                rert.release();
                                rert = null;
                            }
                            if (tempBitmap != null && !tempBitmap.isRecycled()) {
                                tempBitmap.recycle();
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
            return null;
        }
    }

    private class MediaFileLoaderTask extends AsyncTask<String, Void, Void> {
        @Override
        protected void onPreExecute() {
            mediaFileBrowser.setFocusable(false);
            mediaFileBrowser.setEnabled(false);
            mHandler.removeMessages(MSG_START_LOAD_THUMB_TASK);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            MediaFileManager.getInstance().putDirToMediaFilesMap(mCurrentDir, mLocalMediaInfoList);
            fileBrowserAdapter.updateDataAndView(mLocalMediaInfoList);
            int pos = 0;
            if (dirFocusPosMap.containsKey(mCurrentDir)) {
                pos = dirFocusPosMap.get(mCurrentDir);
            }
            mediaFileBrowser.setSelection(pos);
            mediaFileBrowser.setEnabled(true);
            mediaFileBrowser.setFocusable(true);
            tvFilePath.setText(StringUtils.transformFileMountPathToDevNamePath(mCurrentDir, mCurrDeviceInfo.getMountPath(),
                    mCurrDeviceInfo.getDevName()).replaceAll(File.separator, mContext.getResources().getString(R.string.file_replace_separator)));
            mHandler.sendEmptyMessage(MSG_STOP_LOAD_THUMB_TASK);
            mHandler.removeMessages(MSG_START_LOAD_THUMB_TASK);
            mHandler.sendEmptyMessageDelayed(MSG_START_LOAD_THUMB_TASK,1000);
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            if (isCancelled()) {
                return;
            }
            fileBrowserAdapter.updateDataAndView(mLocalMediaInfoList);
        }

        @Override
        protected Void doInBackground(String... strings) {
            String dir = strings[0];
            mLocalMediaInfoList.clear();
            if (MediaFileManager.getInstance().isContainDir(dir)) {
                mLocalMediaInfoList = MediaFileManager.getInstance().getDirToMediaFilesMap(dir);
                return null;
            } else {
                File root = new File(dir);
                File[] usbVolumes = root.listFiles();
                Arrays.sort(usbVolumes, mediaFileComparator);
                for (int i = 0; i < usbVolumes.length; i++) {
                    if (isCancelled()) {
                        break;
                    }
                    LocalMediaInfo info = new LocalMediaInfo(usbVolumes[i]);
                    mLocalMediaInfoList.add(info);
                    if (i % 30 == 0 && i > 0) {
                        publishProgress();
                    }
                }
            }
            return null;
        }
    }
}
